using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Terra.Core.Common.ApiResponse;
using Terra.Service.Identity.DTOs;
using Terra.Service.Identity.Interfaces;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
using Terra.Core.Common.ErrorCodes.Constants;
using Terra.WebApi.Filters;
using Terra.Core.Infrastructure.Email.Interfaces;
using Terra.Core.Common.Extensions;

namespace Terra.WebApi.Areas.Admin.Controllers;

/// <summary>
/// 身份认证控制器
/// </summary>
/// <remarks>
/// 提供以下功能：
/// <list type="bullet">
/// <item><description>用户登录</description></item>
/// <item><description>用户登出</description></item>
/// <item><description>令牌刷新</description></item>
/// <item><description>获取当前用户信息</description></item>
/// <item><description>修改密码</description></item>
/// </list>
/// </remarks>
[Area("Admin")]
[ApiController]
[Route("api/admin/auth")]
[ApiExplorerSettings(GroupName = "v1-admin")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class AuthController : ControllerBase
{
    private readonly IAuthService _authService;
    private readonly ILogger<AuthController> _logger;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="authService">认证服务</param>
    /// <param name="logger">日志记录器</param>

    public AuthController(
        IAuthService authService,
        ILogger<AuthController> logger)
    {
        _authService = authService;
        _logger = logger;
    }

    /// <summary>
    /// 用户登录
    /// </summary>
    /// <param name="request">登录请求</param>
    /// <returns>登录响应</returns>
    /// <response code="200">登录成功</response>
    /// <response code="401">用户名或密码错误</response>
    /// <response code="423">账号已被锁定</response>
    [AllowAnonymous]
    [HttpPost("login")]
    [ProducesResponseType(typeof(ApiResponse<LoginResponseDto>), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    [ProducesResponseType(typeof(ApiResponse), 423)]
    public async Task<IActionResult> LoginAsync([FromBody] LoginRequestDto request)
    {
        var result = await _authService.LoginAsync(request);
        return result.IsSuccess ? Ok(result) : BadRequest(result);
    }

    /// <summary>
    /// 用户登出
    /// </summary>
    /// <returns>登出结果</returns>
    /// <response code="200">登出成功</response>
    /// <response code="401">未授权</response>
    [Authorize]
    [HttpPost("logout")]
    [ProducesResponseType(typeof(ApiResponse), 200)]
    [ProducesResponseType(typeof(ApiResponse), 401)]
    public async Task<IActionResult> LogoutAsync()
    {
        var userId = Guid.Parse(User.FindFirst(ClaimTypes.NameIdentifier)?.Value);
        var result = await _authService.LogoutAsync(userId);
        return Ok(result);
    }

    /// <summary>
    /// 获取当前用户信息
    /// </summary>
    /// <returns>用户信息</returns>
    /// <response code="200">获取成功</response>
    /// <response code="401">未授权</response>
    [Authorize]
    [HttpGet("me")]
    [ProducesResponseType(typeof(ApiResponse<UserDto>), 200)]
    [ProducesResponseType(typeof(ApiResponse), 401)]
    public async Task<IActionResult> GetCurrentUserAsync()
    {
        if (!User.Identity.IsAuthenticated)
        {
            return Unauthorized(ApiResponse.Error("AUTH002", "未经授权的访问"));
        }

        var userId = User.GetUserId();
        if (!userId.HasValue)
        {
            return Unauthorized(ApiResponse.Error("AUTH002", "无效的用户标识"));
        }

        var result = await _authService.GetUserInfoAsync(userId.Value);
        return result.IsSuccess ? Ok(result) : Unauthorized(result);
    }

    /// <summary>
    /// 刷新访问令牌
    /// </summary>
    /// <param name="request">刷新令牌请求</param>
    /// <returns>新的访问令牌</returns>
    /// <response code="200">刷新成功</response>
    /// <response code="400">刷新令牌无效</response>
    [AllowAnonymous]
    [HttpPost("refresh-token")]
    [ProducesResponseType(typeof(ApiResponse<TokenResponseDto>), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    public async Task<IActionResult> RefreshTokenAsync([FromBody] RefreshTokenRequestDto request)
    {
        var result = await _authService.RefreshTokenAsync(request);
        return result.IsSuccess ? Ok(result) : BadRequest(result);
    }

    /// <summary>
    /// 修改密码
    /// </summary>
    /// <param name="request">修改密码请求</param>
    /// <returns>修改结果</returns>
    /// <response code="200">修改成功</response>
    /// <response code="400">请求无效</response>
    /// <response code="401">未授权</response>
    [Authorize]
    [HttpPost("change-password")]
    [ProducesResponseType(typeof(ApiResponse), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    [ProducesResponseType(typeof(ApiResponse), 401)]
    public async Task<IActionResult> ChangePasswordAsync([FromBody] ChangePasswordRequestDto request)
    {
        var userId = Guid.Parse(User.FindFirst(ClaimTypes.NameIdentifier)?.Value);
        var result = await _authService.ChangePasswordAsync(userId, request);
        return result.IsSuccess ? Ok(result) : BadRequest(result);
    }

    /// <summary>
    /// 用户注册
    /// </summary>
    /// <param name="request">注册请求</param>
    /// <returns>注册响应</returns>
    /// <response code="200">注册成功</response>
    /// <response code="400">请求数据验证失败</response>
    /// <response code="409">用户名或邮箱已存在</response>
    [AllowAnonymous]
    [HttpPost("register")]
    [ProducesResponseType(typeof(ApiResponse<RegisterResponseDto>), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    [ProducesResponseType(typeof(ApiResponse), 409)]
    public async Task<IActionResult> RegisterAsync([FromBody] RegisterRequestDto request)
    {
        var result = await _authService.RegisterAsync(request);

        if (!result.IsSuccess)
        {
            // 根据错误码返回适当的HTTP状态码
            return result.Code switch
            {
                SecurityErrorCodes.UserNameAlreadyExists or
                SecurityErrorCodes.EmailAlreadyExists or
                SecurityErrorCodes.PhoneNumberAlreadyExists
                    => Conflict(result),
                _ => BadRequest(result)
            };
        }

        return Ok(result);
    }

    #region 密码重置

    /// <summary>
    /// 发起密码重置
    /// </summary>
    /// <returns>操作结果</returns>
    /// <response code="200">发送重置请求成功</response>
    /// <response code="400">请求参数无效</response>
    /// <response code="404">用户不存在</response>
    [AllowAnonymous]
    [HttpPost("reset-password/initiate")]
    [ProducesResponseType(typeof(ApiResponse), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    [ProducesResponseType(typeof(ApiResponse), 404)]
    public async Task<IActionResult> InitiatePasswordResetAsync(
        [FromBody] InitiatePasswordResetRequestDto request)
    {
        var operatorId = User.Identity.IsAuthenticated
            ? User.FindFirst(ClaimTypes.NameIdentifier)?.Value
            : null;

        var result = await _authService.InitiatePasswordResetAsync(
            request.Account,
            request.ResetType,
            operatorId);

        if (!result.IsSuccess)
        {
            return result.Code switch
            {
                SecurityErrorCodes.UserNotFound => NotFound(result),
                _ => BadRequest(result)
            };
        }

        return Ok(result);
    }

    /// <summary>
    /// 验证并重置密码
    /// </summary>
    /// <param name="request">重置密码请求</param>
    /// <returns>重置结果</returns>
    /// <response code="200">密码重置成功</response>
    /// <response code="400">请求参数无效或密码强度不足</response>
    /// <response code="404">用户不存在</response>
    [AllowAnonymous]
    [HttpPost("reset-password/validate")]
    [ProducesResponseType(typeof(ApiResponse), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    [ProducesResponseType(typeof(ApiResponse), 404)]
    public async Task<IActionResult> ValidateAndResetPasswordAsync(
        [FromBody] ValidatePasswordResetRequestDto request)
    {
        var result = await _authService.ValidateAndResetPasswordAsync(
            request.Token,
            request.NewPassword,
            request.ResetType);

        if (!result.IsSuccess)
        {
            return result.Code switch
            {
                SecurityErrorCodes.UserNotFound => NotFound(result),
                SecurityErrorCodes.InvalidResetToken or
                SecurityErrorCodes.PasswordStrengthInsufficient => BadRequest(result),
                _ => BadRequest(result)
            };
        }

        return Ok(result);
    }

    /// <summary>
    /// 检查密码状态
    /// </summary>
    /// <returns>密码状态检查结果</returns>
    /// <response code="200">检查成功</response>
    /// <response code="401">未授权</response>
    /// <response code="404">用户不存在</response>
    [Authorize]
    [HttpGet("password/status")]
    [ProducesResponseType(typeof(ApiResponse<PwdResetDtos>), 200)]
    [ProducesResponseType(typeof(ApiResponse), 401)]
    [ProducesResponseType(typeof(ApiResponse), 404)]
    public async Task<IActionResult> CheckPasswordStatusAsync()
    {
        var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (string.IsNullOrEmpty(userId))
        {
            return Unauthorized(ApiResponse.Error(SecurityErrorCodes.Unauthorized));
        }

        var result = await _authService.CheckPasswordStatusAsync(userId);

        if (!result.IsSuccess)
        {
            return result.Code switch
            {
                SecurityErrorCodes.UserNotFound => NotFound(result),
                _ => BadRequest(result)
            };
        }

        return Ok(result);
    }

    /// <summary>
    /// 重置初始密码
    /// </summary>
    /// <param name="request">重置初始密码请求</param>
    /// <returns>重置结果</returns>
    /// <response code="200">重置成功</response>
    /// <response code="400">请求参数无效或当前密码错误</response>
    /// <response code="401">未授权</response>
    /// <response code="404">用户不存在</response>
    [Authorize]
    [HttpPost("password/reset-initial")]
    [ProducesResponseType(typeof(ApiResponse), 200)]
    [ProducesResponseType(typeof(ApiResponse), 400)]
    [ProducesResponseType(typeof(ApiResponse), 401)]
    [ProducesResponseType(typeof(ApiResponse), 404)]
    public async Task<IActionResult> ResetInitialPasswordAsync(
        [FromBody] ResetInitialPasswordRequestDto request)
    {
        var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (string.IsNullOrEmpty(userId))
        {
            return Unauthorized(ApiResponse.Error(SecurityErrorCodes.Unauthorized));
        }

        var result = await _authService.ResetInitialPasswordAsync(
            userId,
            request.CurrentPassword,
            request.NewPassword);

        if (!result.IsSuccess)
        {
            return result.Code switch
            {
                SecurityErrorCodes.UserNotFound => NotFound(result),
                SecurityErrorCodes.InvalidCredentials => BadRequest(result),
                _ => BadRequest(result)
            };
        }

        return Ok(result);
    }

    #endregion

    /// <summary>
    /// 测试邮件发送功能 (仅用于开发环境调试)
    /// </summary>
    [AllowAnonymous]
    [HttpGet("test-email")]
    [ApiExplorerSettings(IgnoreApi = true)]
    public async Task<IActionResult> TestEmailAsync([FromQuery] string email)
    {
        try
        {
            // 获取邮件发送服务
            var emailSender = HttpContext.RequestServices.GetRequiredService<IEmailSender>();

            // 发送测试邮件
            var subject = "Terra系统测试邮件";
            var body = @"
                <h2>这是一封测试邮件</h2>
                <p>如果您收到这封邮件，说明您的邮件服务配置正确。</p>
                <p>发送时间: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + @"</p>
                <p>祝好,<br>Terra团队</p>";

            var result = await emailSender.SendAsync(email, subject, body, true);

            if (result)
            {
                _logger.LogInformation("测试邮件发送成功: {Email}", email);
                return Ok(new { success = true, message = "测试邮件发送成功" });
            }
            else
            {
                _logger.LogWarning("测试邮件发送失败: {Email}", email);
                return BadRequest(new { success = false, message = "测试邮件发送失败，请检查日志获取详细信息" });
            }
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "测试邮件发送异常");
            return StatusCode(500, new { success = false, message = $"邮件发送异常: {ex.Message}" });
        }
    }
}